package com.nexus.plugin.security;

import com.nexus.core.exception.AuthenicException;
import com.nexus.core.auth.LoginUser;
import com.nexus.plugin.security.constants.AuthConstants;
import com.nexus.plugin.security.utils.JwtTokenProvider;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Optional;

/**
 * 安全工具类，封装SecurityContextHolder的操作
 *
 * @Date 2025/8/1 09:39
 * @Author luzhengning
 **/
public class SecurityUtils {

    /**
     * 注册登录用户，生成Token，记录到到Redis
     * 必须登录认证通过后调用
     *
     * @Date 2025/8/1 15:31
     * @Author luzhengning
     **/
    public static LoginUser RegisterLoginUser(LoginUser loginUser) throws AuthenicException {
        // 生成token
        String token = JwtTokenProvider.createToken(loginUser, AuthConstants.ACCESS_TOKEN_EXPIRE_HOUR);
        loginUser.setAccessToken(token);
        // 生成刷新refreshToken
        String refreshToken = JwtTokenProvider.createToken(loginUser, AuthConstants.REFRESH_TOKEN_EXPIRE_HOUR);
        loginUser.setRefreshToken(refreshToken);
        // 设置登录时间
        loginUser.setLoginDate(LocalDateTime.now());
        // token过期时间
        loginUser.setExpires(JwtTokenProvider.calculateExpireTime(null,AuthConstants.ACCESS_TOKEN_EXPIRE_HOUR));
        // 保存登录用户到redis中
        SecurityCache.setLoginUser(loginUser.getUsername(), loginUser);
        return loginUser;
    }

    /**
     * 解析Token并设置认证信息到当前上下文
     *
     * @param token 登录的Token
     */
    public static Authentication setAuthentication(String token) throws AuthenicException {
        // 解析Token中的登录信息
        LoginUser loginUser = JwtTokenProvider.getLoginUser(token);
        // 从系统缓存中获取完整的登录信息
        loginUser = SecurityCache.getLoginUser(loginUser.getUsername());
        Collection<? extends GrantedAuthority> authorities = loginUser.getAuthorities();

        // 封装Security认证信息
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, authorities);
        // 保存到Security上下文中
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(usernamePasswordAuthenticationToken);
        return usernamePasswordAuthenticationToken;
    }

    /**
     * 获取当前登录用户
     *
     * @Date 2025/8/1 16:22
     * @Author luzhengning
     **/
    public static LoginUser getCurrentLoginUser() {
        Optional<Authentication> currentAuthentication = getCurrentAuthentication();
        if (currentAuthentication.isPresent()) {
            Object principal = currentAuthentication.get().getPrincipal();
            return (LoginUser) principal;
        }
        return null;
    }

    /**
     * 获取当前认证信息
     *
     * @return 认证信息Optional对象
     */
    public static Optional<Authentication> getCurrentAuthentication() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        return Optional.ofNullable(securityContext.getAuthentication());
    }

    /**
     * 获取当前登录用户名
     *
     * @return 用户名Optional对象，未登录则为空
     */
    public static Optional<String> getCurrentUsername() {
        return getCurrentAuthentication().filter(authentication -> !(authentication instanceof AnonymousAuthenticationToken)).map(authentication -> {
            Object principal = authentication.getPrincipal();
            if (principal instanceof UserDetails) {
                return ((UserDetails) principal).getUsername();
            } else if (principal instanceof String) {
                return (String) principal;
            }
            return null;
        });
    }

    /**
     * 检查当前用户是否已认证（非匿名用户）
     *
     * @return 已认证返回true，否则返回false
     */
    public static boolean isAuthenticated() {
        return getCurrentAuthentication().map(authentication -> !(authentication instanceof AnonymousAuthenticationToken) && authentication.isAuthenticated()).orElse(false);
    }

    /**
     * 检查当前用户是否拥有指定角色
     *
     * @param role 角色名称（注意：需要包含ROLE_前缀，如"ROLE_ADMIN"）
     * @return 拥有该角色返回true，否则返回false
     */
    public static boolean hasRole(String role) {
        return getCurrentAuthentication().filter(authentication -> isAuthenticated()).map(authentication -> authentication.getAuthorities().stream().anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(role))).orElse(false);
    }

    /**
     * 检查当前用户是否拥有指定权限
     *
     * @param permission 权限名称
     * @return 拥有该权限返回true，否则返回false
     */
    public static boolean hasPermission(String permission) {
        return getCurrentAuthentication().filter(authentication -> isAuthenticated()).map(authentication -> authentication.getAuthorities().stream().anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(permission))).orElse(false);
    }

    /**
     * 获取当前用户的认证对象
     *
     * @return 认证对象Optional，未认证则为空
     */
    public static Optional<Object> getCurrentPrincipal() {
        return getCurrentAuthentication().filter(authentication -> isAuthenticated()).map(Authentication::getPrincipal);
    }

    /**
     * 清除当前线程的安全上下文
     */
    public static void clearContext() {
        SecurityContextHolder.clearContext();
    }


}
